package com.example.sso.service.mp.api.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.example.rose.common.enums.TokenType;
import com.example.sso.service.model.dto.MemberLoginDTO;
import com.example.sso.service.model.vo.MemberLoginVO;
import com.example.sso.service.mp.api.entity.Member;
import com.example.sso.service.mp.api.mapper.MemberMapper;
import com.example.sso.service.mp.api.service.MemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuyunbin.jwt.util.JwtUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * <p>
 * 会员表 服务实现类
 * </p>
 *
 * @author wuyunbin
 * @since 2025-02-22
 */
@Slf4j
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {

    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private WxMaService wxMaService;



    @Override
    public MemberLoginVO login(MemberLoginDTO memberLoginDTO) {

        String openId = "";

        try {
            //获取openId
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(memberLoginDTO.getCode());
            openId = session.getOpenid();
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }

        Member member = this.getByOpenId(openId);

        if (member == null) {
            member = new Member();
            member.setOpenId(openId);
            this.save(member);
            //可能需要跨服务存数据
        }

        //检查手机号？

        Function<Member, Map<String, Object>> converter = (m) -> {
            Map<String, Object> claims = new HashMap<>();
            claims.put("memberId", m.getMemberId());
            claims.put("type", TokenType.ACCESS_TOKEN);
            return claims;
        };

        /*
        accessToken:读写数据，有效期比较短的token，5min
        refreshToken:刷新accessToken和refreshToken，有效期比较长的token,7天，一次性的
         */
        String accessToken = jwtUtil.createAccessToken(member, converter);
        log.info("accessToken:{}", accessToken);

        converter = (m) -> {
            Map<String, Object> claims = new HashMap<>();
            claims.put("memberId", m.getMemberId());
            claims.put("type", TokenType.REFRESH_TOKEN);
            return claims;
        };

        String refreshToken = jwtUtil.createRefreshToken(member, converter);
        log.info("refreshToken:{}", refreshToken);
        //把两个token存入到redis hash
        return MemberLoginVO.builder()
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .build();
    }

    @Override
    public MemberLoginVO getTokensByRefreshToken(String refreshToken) {
        //判断refreshToken是否合法
        String s = jwtUtil.validateToken(refreshToken);
        log.info("s:{}", s);
        Member member = null;
        if ("Valid".equals(s)) {
            String id = jwtUtil.parseToken(refreshToken).get("memberId", String.class);
            member = this.getById(id);
        }

        Function<Member, Map<String, Object>> converter = (m) -> {
            Map<String, Object> claims = new HashMap<>();
            claims.put("memberId", m.getMemberId());
            claims.put("type", TokenType.ACCESS_TOKEN);
            return claims;
        };

        /*
        accessToken:读写数据，有效期比较短的token，5min
        refreshToken:刷新accessToken和refreshToken，有效期比较长的token,7天，一次性的
         */
        String newAccessToken = jwtUtil.createAccessToken(member, converter);
        log.info("accessToken:{}", newAccessToken);

        converter = (m) -> {
            Map<String, Object> claims = new HashMap<>();
            claims.put("memberId", m.getMemberId());
            claims.put("type", TokenType.REFRESH_TOKEN);
            return claims;
        };

        String newRefreshToken = jwtUtil.createRefreshToken(member, converter);
        log.info("refreshToken:{}", refreshToken);

        return MemberLoginVO.builder()
                .accessToken(newAccessToken)
                .refreshToken(newRefreshToken)
                .build();
    }

    @Override
    public Member getByOpenId(String openId) {
        return this.lambdaQuery().eq(Member::getOpenId, openId).one();
    }
}
